﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Text;
using System.Windows.Forms;

namespace Clotho
{
	public abstract class IFeature : IItem {
		public abstract string Type_word { get; }
		protected string name;
		public event EventHandler<TEventArgs<string>> eNameChanging;
		public string Name {
			get {
				return name;
			}
			set {
				if (name == value) {
					return;
				}
				if (this.Parent.Features.Exists(p => p.Name == value)) {
					throw new InvalidCmd_Exception(this, $"不能将属性【{name}】的名字改为{value}，否则会造成名字重复。");
				}
				string old = name;
				Nov.doCmd(() => {
					eNameChanging?.Invoke(this, new TEventArgs<string>(value));
					name = value;
				}, () => {
					eNameChanging?.Invoke(this, new TEventArgs<string>(old));
					name = old;
				});
			}
		}

		public readonly IItem Parent;
		public Novel Nov => Parent.Nov;
		public List<string> Path {
			get {
				var temp = Parent.Path;
				temp.Add(Name);
				return temp;
			}
		}
		public abstract IFeature Clone(IItem parent);
		public IFeature(IItem parent, string n) {
			Parent = parent;
			name = n;
			Parent.Features.Add(this);
		}
		public virtual void remove() {
			Parent.Features.Remove(this);
		}

		public virtual List<IFeature> Features { get; protected set; } = null;

		public static readonly (string str, int len)[] Level_mark = {
			("\n ",                       2+0) ,
			("\n# ",                      2+1) ,
			("\n## ",                     2+2) ,
			("\n### ",                    2+3) ,
			("\n#### ",                   2+4) ,
			("\n##### ",                  2+5) ,
			("\n###### ",                 2+6) ,
			("\n####### ",                2+7) ,
			("\n######## ",               2+8) ,
			("\n######### ",              2+9) ,
		};
		public static readonly char delimiter = '|';
		public static readonly char type_name_del = '-';

		protected void writeString(StringBuilder sb,string str) {
			sb.Append(delimiter); 
			sb.Append(str);
		}

		protected virtual void writeDatas(StringBuilder str) {
			return;
		}

		public virtual void writeToStr(int level, StringBuilder sb) {
			sb.Append(Level_mark[level].str);
			sb.Append(Type_word);
			sb.Append('-');
			sb.Append(Name);
			writeDatas(sb);
			if (Features != null) {
				foreach (var feature in Features) {
					feature.writeToStr(level+1, sb);
				}
			}
		}
		/// <summary>
		/// 以指定的标题等级从字符串加载本属性
		/// </summary>
		/// <param name="str">描述本属性的字符串的后半部分
		/// </param>
		/// <param name="level">标题等级，如果属性发送嵌套，则下一级属性的标题为level+1</param>
		public virtual void loadFeatureData(string str) {
			return;
		}
		/// <summary>
		/// 从字符串读取后续参数
		/// </summary>
		/// <param name="ss">后续的参数，偏移从1开始，其中ss[0]是读取到的名字。</param>
		public virtual void loadData(string[] ss) {
			return;
		}



		/// <summary>
		/// 接受一个属性字符串，以“ \n##……# ”分割，提取其中的属性，并存入 给定的features 
		/// </summary>
		/// <param name="all_str">一个字符串，形如：
		/// ## 显示-base|300|300
		/// ## 要点-李瓘
		/// ## 要点-皖承
		/// </param>
		/// <param name="level">解析字符串时 #的数量</param>
		/// <param name="feature_factory">属性工厂，用于记录属性类和Type字符串的关系</param>
		/// <param name="parent">传入拥有这些属性的父结构，通常是Plot，也可能是IFeature</param>
		/// <returns>返回转换成功的个数</returns>
		/// <exception cref="Exception"></exception>
		public static int readAllFeatureFromStr(string all_str, int level, FeatureFactory feature_factory, IItem parent) {//这里需要整理一下
			return parseFeatureString(all_str, level, s => parse(s));
			
			void parse(string item_str) {
				//将数据分为四部分，分别是level_mark，第一行，后续定义，子feature
				var lm = Level_mark[level];
				int lm_end = lm.len;
				IFeature fea;
				int first_line_end = item_str.IndexOf('\n', lm_end);
				if (first_line_end == -1) {//如果没有找到行尾
					loadFirstLine(item_str.Substring(lm_end));//全部数据只有一行。
				} else {//如果后面还有
					loadFirstLine(item_str.Substring(lm_end, first_line_end- lm_end));//将这一行分出来
					
					//在后续数据中寻找子属性的开头
					var sub_lm = Level_mark[level+1];
					int feature_end = item_str.IndexOf(sub_lm.str, first_line_end);
					if (feature_end == -1) {//如果没有找到
						fea.loadFeatureData(item_str.Substring(first_line_end));//全部都是后续数据
					} else {//如果找到了
						fea.loadFeatureData(item_str.Substring(first_line_end, feature_end- first_line_end));//处理后续数据
						readAllFeatureFromStr(item_str.Substring(feature_end), level + 1, feature_factory, fea);//加载子属性。
					}
				}

				void loadFirstLine(string str) {
					int end = str.IndexOf(type_name_del, 0);
					if (end == -1) {
						throw new Exception($"无法找到字符串中 类型 和 名字 的分隔符'-'：\n{item_str}");
					}
					string type_str = str.Substring(0, end);
					string[] ss = str.Substring(end + 1).Split(delimiter);
					string name = ss[0];
					fea = feature_factory.getFeature(type_str, parent, name);
					fea.loadData(ss);
				}
			}
		}
		/// <summary>
		/// 将字符串按照level定义的分割标记，分成多个字符串，然后使用pares处理
		/// </summary>
		/// <param name="str">整个数据的字符串</param>
		/// <param name="level">分割符的等级，也就是“#”的数量</param>
		/// <param name="parse">处理每个分割好的字符串的回调函数</param>
		/// <returns>返回分割好的字符串的数量</returns>
		public static int parseFeatureString(string str, int level, Action<string> parse) {
			int ptr, end, feature_count;
			string lm = Level_mark[level].str;
			feature_count = 0;
			ptr = str.IndexOf(lm);
			if (ptr == -1) {
				return feature_count;
			}
			while (true) {
				end = str.IndexOf(lm, ptr + 1);
				if (end == -1) {
					end = str.Length;
					feature_count++;
					parse(str.Substring(ptr, end - ptr));
					return feature_count;
				}
				feature_count++;
				parse(str.Substring(ptr, end - ptr));
				ptr = end;
			}
		}

	}
	public class FeatureFactory {
		Dictionary<string,Type> Feature_table = new Dictionary<string,Type>();
		public void registerFeature(Type feature_type) {
			string s = feature_type.GetField("TYPEWORD",  BindingFlags.Static | BindingFlags.Public).GetValue(null) as string;
			Feature_table.Add(s, feature_type);
		}
		public IFeature getFeature(string type_word, IItem parent, string name) {
			if (Feature_table.ContainsKey(type_word)) {
				return Activator.CreateInstance(Feature_table[type_word], parent, name) as IFeature;
			} else {
				return null;
			}
		}
	}
}
